package org.jeecg.modules.ws.util;

import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 网银直连客户端工具类
 */
@Slf4j
@Component
public class WyzlClient {

    @Value("${wyzl.host:localhost}")
    private String host;

    @Value("${wyzl.port:12345}")
    private int port;

    @Value("${wyzl.communicationType:http}")
    private String communicationType;

    @Value("${wyzl.encryptType:SMFace}")
    private String encryptType;

    @Value("${wyzl.custId:}")
    private String custId;

    @Value("${wyzl.userId:}")
    private String userId;

    @Value("${wyzl.password:}")
    private String password;

    private final XmlMapper xmlMapper;

    public WyzlClient() {
        this.xmlMapper = new XmlMapper();
        // 设置XML编码为GB2312
        this.xmlMapper.getFactory().getXMLOutputFactory().setProperty("javax.xml.stream.isRepairingNamespaces", false);

        // 配置日期格式
        this.xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        this.xmlMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        this.xmlMapper.setDateFormat(new SimpleDateFormat("yyyy/MM/dd"));

        // 注册Java 8日期时间模块
        this.xmlMapper.registerModule(new JavaTimeModule());
    }

    /**
     * 发送余额查询请求
     *
     * @param request 请求对象
     * @return 响应对象
     */
    public WyzlBalanceResponse queryBalance(WyzlBalanceRequest request) throws Exception {
        // 设置交易码
        request.setTxCode("6W0100");
        // 设置请求序列号
        request.setRequestSn(generateRequestSn());
        // 设置客户号
        request.setCustId(custId);
        // 设置操作员号
        request.setUserId(userId);
        // 设置密码
        request.setPassword(password);
        // 设置语言
        request.setLanguage("CN");

        String xmlRequest = convertToXml(request);
        System.out.println(xmlRequest);
        String xmlResponse = sendRequest(xmlRequest);
        System.out.println(xmlResponse);
        return xmlMapper.readValue(xmlResponse, WyzlBalanceResponse.class);
    }

    /**
     * 发送账户明细查询请求
     *
     * @param request 请求对象
     * @return 响应对象
     */
    public WyzlAccountDetailResponse queryAccountDetail(WyzlAccountDetailRequest request) throws Exception {
        // 设置交易码
        request.setTxCode("6WY101");
        // 设置请求序列号
        request.setRequestSn(generateRequestSn());
        // 设置客户号
        request.setCustId(custId);
        // 设置操作员号
        request.setUserId(userId);
        // 设置密码
        request.setPassword(password);
        // 设置语言
        request.setLanguage("CN");

        String xmlRequest = convertToXml(request);
        System.out.println(xmlRequest);
        String xmlResponse = sendRequest(xmlRequest);
        System.out.println(xmlResponse);
        return xmlMapper.readValue(xmlResponse, WyzlAccountDetailResponse.class);
    }

    /**
     * 发送请求
     *
     * @param xmlRequest XML请求报文
     * @return XML响应报文
     */
    private String sendRequest(String xmlRequest) throws Exception {
        if ("http".equalsIgnoreCase(communicationType)) {
            return sendHttpRequest(xmlRequest);
        } else {
            return sendSocketRequest(xmlRequest);
        }
    }

    /**
     * 发送HTTP请求
     */
    private String sendHttpRequest(String xmlRequest) throws Exception {
        String url = "http://" + host + ":" + port;
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        log.info("请求地址:{}",url);

        try {
            // 设置超时时间：1分钟（60秒）
            connection.setConnectTimeout(60 * 1000);
            connection.setReadTimeout(60 * 1000);

            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=GB2312");
            connection.setRequestProperty("Accept-Charset", "GB2312");

            String requestBody = "requestXml=" + xmlRequest;
            if (StringUtils.hasText(encryptType)) {
                requestBody = "encryptType=" + encryptType + "&" + requestBody;
            }
            log.info("请求参数:{}",requestBody);

            try (OutputStream os = connection.getOutputStream()) {
                os.write(requestBody.getBytes("GB2312"));
            }

            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(connection.getInputStream(), "GB2312"))) {
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                return response.toString();
            }
        } finally {
            connection.disconnect();
        }
    }

    /**
     * 发送Socket请求
     */
    private String sendSocketRequest(String xmlRequest) throws Exception {
        try (Socket socket = new Socket(host, port);
             OutputStream os = socket.getOutputStream();
             InputStream is = socket.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is, "GB2312"))) {

            // 发送请求
            os.write(xmlRequest.getBytes("GB2312"));
            os.flush();

            // 读取响应
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
                if (line.contains("</TX>")) {
                    break;
                }
            }
            return response.toString();
        }
    }

    /**
     * 将对象转换为XML
     */
    private String convertToXml(Object obj) throws Exception {
        return xmlMapper.writeValueAsString(obj);
    }

    /**
     * 生成请求序列号
     * 格式：yyyyMMddHHmmss + 4位随机数
     */
    private String generateRequestSn() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String timestamp = sdf.format(new Date());
        int random = (int) (Math.random() * 9000) + 1000;
        return timestamp + random;
    }
}
